package com.bfxy.rabbitmq.consumer.component;

import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import com.rabbitmq.client.Channel;

import java.util.Objects;

@Component
public class RabbitReceive {
	
	/**
	 * @RabbitListener @QueueBinding @Queue @Exchange 这些注解组合使用监听队列
	 * @param message
	 * @param channel
	 * @throws Exception
	 */
	@RabbitListener(bindings = @QueueBinding(
					value = @Queue(value = "${spring.rabbitmq.listener.order.queue.name}", durable = "${spring.rabbitmq.listener.order.queue.durable}"),
					exchange = @Exchange(name = "${spring.rabbitmq.listener.order.exchange.name}",
					durable = "${spring.rabbitmq.listener.order.exchange.durable}",
					type = "${spring.rabbitmq.listener.order.exchange.type}",
					ignoreDeclarationExceptions = "true"),
					key = "${spring.rabbitmq.listener.order.exchange.key}"
				)
			)
	@RabbitHandler
	public void onMessage(Message message, Channel channel) throws Exception {
		// 1. 收到消息以后进行业务端消费处理
		System.err.println("-----------------------");
		System.err.println("消费消息:" + message.getPayload());

		// 2. 处理成功之后 获取deliveryTag 并进行手工的ACK操作, 因为我们配置文件里配置的是手工签收：spring.rabbitmq.listener.simple.acknowledge-mode=manual
		// 消息的唯一标识ID，是一个正整数，是mq来自增设置的，不用在消息手动设置在消息中
		long deliveryTag =  Long.parseLong(Objects.requireNonNull(message.getHeaders().get(AmqpHeaders.DELIVERY_TAG)).toString());
		channel.basicAck(deliveryTag, false); // RabbitMQ在未接收到消费端的ACK后，仍然会将未ACK的消息再发给消费端直至收到消费端的ACK，故做消息的可靠性投递只需要做生产端与MQ之间的消息传输即可，消费端的可靠性投递大多数MQ都已经内部实现
	}
	
}
